package exatrez.stripes;

import able.stripes.JSP;
import com.google.inject.Inject;
import com.wideplay.warp.persist.Transactional;
import exatrez.dao.PenggunaDAO;
import exatrez.manager.UserManager;
import exatrez.model.User;
import exatrez.service.session.LoginSession;
import exatrez.service.session.SessionManager;
import exatrez.stripes.config.ableActionBeanContext;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationMethod;
import org.apache.log4j.Logger;


@UrlBinding("/login")
public class LoginActionBean extends WelcomeActionBean {
   
    @Validate(required=true, label="User ID")
    private String userLogin;
    @Validate(required=true, label="Password")
    private String userPassword;    

    @Inject
    private UserManager userManager = new UserManager();    
    @Inject
    Configuration conf;
    @Inject
    private PenggunaDAO penggunaDAO;
    
    private int sesMaxAttempt;
    private int lockInterval;
    private boolean doLock = false;
    private String cookieLockName = "lockSession";
    private String cookieExpName  = "expSession";
   
    private static Logger LOG = Logger.getLogger(LoginActionBean.class);
    
    @DefaultHandler
    @DontValidate
    public Resolution showForm() {
        HttpServletRequest request = context.getRequest();
        HttpSession session = request.getSession(false);
        Cookie[] cookies = request.getCookies();
        boolean isCookie = false;
        if(cookies.length > 0){
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals(cookieLockName)){
                    isCookie = true;
                }
            }
        }
        int i = session.getAttribute("loginCount") != null ? Integer.parseInt(session.getAttribute("loginCount").toString()) : 0;
        if((session != null || !session.isNew()) && (i >= getSesMaxAttempt() || isCookie)){
//            int sesAttempt = Integer.parseInt(session.getAttribute("loginCount").toString());
            return new JSP("lock.jsp");
        }
        return new JSP("login.jsp");
    } 
    
    public Resolution login() {       
        
        return new RedirectResolution(WelcomeActionBean.class);        
    }

    @ValidationMethod
    @Transactional
    public void validate_login() {          
     
        String adAuth = conf.getProperty("activeD.authenticate");
        boolean activeDAuth = Boolean.parseBoolean(adAuth);
        
        System.out.println("(LoginActionBean) validate_login => activeDAuth :"+activeDAuth);
        
        //start session login attempt
        HttpSession session = context.getRequest().getSession(false);
        String msg = "";
        int sesAttempt = 1;
        
        try{
            sesAttempt = Integer.parseInt(session.getAttribute("loginCount").toString());
            sesAttempt = sesAttempt + 1;            
            session.setAttribute("loginCount", sesAttempt);
        }catch(Exception ex){
            session.setAttribute("loginCount", 1);
        }
        
        if(sesAttempt >= getSesMaxAttempt()){
            msg = "<br /> Your login attempt : "+sesAttempt+" / "+getSesMaxAttempt()+".";
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss a");
            Date sesExp = new Date(System.currentTimeMillis()+getLockInterval()*1000);
            
            Cookie cookie = new Cookie(cookieLockName, "alreadyLock");
            cookie.setMaxAge(getLockInterval());
            context.getResponse().addCookie(cookie);
            
            Cookie cookieExp = new Cookie(cookieExpName, sdf.format(sesExp));
            cookieExp.setMaxAge(getLockInterval());
            context.getResponse().addCookie(cookieExp);
            
            session.setAttribute("sesExpired", sdf.format(sesExp));
            doLock = true;
        }else{
            msg = "<br /> Your login attempt : "+sesAttempt+" / "+getSesMaxAttempt()+".";
        }
        //finish session login attempt
        
        if(getUserLogin().equals("admin")){
            activeDAuth = false;
            System.out.println("(LoginActionBean) validate_login > admin login, activeDAuth :"+activeDAuth);
        }
        
        if(activeDAuth){
            User user = penggunaDAO.findById(getUserLogin());
            if(user == null){
                addSimpleError("Wrong Information."+msg);
            }else{
                ActiveDActionBean activeD = new ActiveDActionBean();
                if(activeD.authenticateAD(user.getAdName(), getUserPassword())){
                    SessionManager sm = SessionManager.getInstance();
                    LoginSession ls = sm.getActiveSessionByUserId(getUserLogin());
                     if (ls != null) {
                         System.out.println("User \"" + getUserLogin() + "\" has been log in at \" + formatSDF(ls.getDateCreated())");
//                         allow multiple session
//                         addSimpleError("User \"" + getUserLogin() + "\" "
//                                    + "has been log in at " + formatSDF(ls.getDateCreated()) );
//                         return;
                     }

                    HttpSession ses = context.getRequest().getSession();
                    ses.setAttribute(ableActionBeanContext.USER_ID_KEY, getUserLogin());

                    sm.addSession(ses.getId(), getUserLogin(), new Date(),
                            context.getRequest().getRemoteAddr(), context.getRequest().getRemoteHost());
                    
                    session.removeAttribute("loginCount");
                    session.removeAttribute("sessionExp");
                }else{
                    addSimpleError("Wrong User ID or Password."+msg);
                }
            }
            
        }else{
            if (!userManager.authenticate(getUserLogin(), getUserPassword())) {
                 addSimpleError("Wrong User ID or Password."+msg);            
             } else {

                SessionManager sm = SessionManager.getInstance();
                 LoginSession ls = sm.getActiveSessionByUserId(getUserLogin());
                  if (ls != null) {
                      System.out.println("User \"" + getUserLogin() + "\" has been log in at \"" + formatSDF(ls.getDateCreated()));
//                      allow multiple session
//                      addSimpleError("User \"" + getUserLogin() + "\" "
//                                 + "has been log in at " + formatSDF(ls.getDateCreated()) );
//                      return;
                  }

                 HttpSession ses = context.getRequest().getSession();
                 ses.setAttribute(ableActionBeanContext.USER_ID_KEY, getUserLogin());

                 sm.addSession(ses.getId(), getUserLogin(), new Date(),
                         context.getRequest().getRemoteAddr(), context.getRequest().getRemoteHost());

                 session.removeAttribute("loginCount");
                 session.removeAttribute("sessionExp");
             }        
        }
    }
    
    private String formatSDF(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a");
        return sdf.format(date);
    }

    public String getUserLogin() {
        return userLogin;
    }

    public void setUserLogin(String userLogin) {
        this.userLogin = userLogin;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public int getSesMaxAttempt() {        
        sesMaxAttempt = Integer.parseInt(conf.getProperty("ses.login.maxAttempt"));
        return sesMaxAttempt;
    }

    public void setSesMaxAttempt(int sesMaxAttempt) {
        this.sesMaxAttempt = sesMaxAttempt;
    } 

    public int getLockInterval() {
        lockInterval = Integer.parseInt(conf.getProperty("ses.login.lockSession"));
        return lockInterval;
    }

    public void setLockInterval(int lockInterval) {
        this.lockInterval = lockInterval;
    }

    public boolean isDoLock() {
        return doLock;
    }

    public void setDoLock(boolean doLock) {
        this.doLock = doLock;
    }

    public String getCookieLockName() {
        return cookieLockName;
    }

    public void setCookieLockName(String cookieLockName) {
        this.cookieLockName = cookieLockName;
    }

    public String getCookieExpName() {
        return cookieExpName;
    }

    public void setCookieExpName(String cookieExpName) {
        this.cookieExpName = cookieExpName;
    }

}
